home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / CODECS.ZIP / codecs / english / dcodlzw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-13  |  14.8 KB  |  401 lines

  1. /* File: dcodlzw.c
  2.    Author: David Bourgin
  3.    Creation date: 25/3/95
  4.    Last update: 12/10/95
  5.    Purpose: Example of LZW decoding with a file source to decompress.
  6. */
  7.  
  8. #include <stdio.h>
  9. /* For routines printf,fgetc,fputc. */
  10. #include <stdlib.h>
  11. /* For routine exit. */
  12.  
  13. /* Error codes returned to the caller. */
  14. #define NO_ERROR             0
  15. #define BAD_FILE_NAME        1
  16. #define BAD_ARGUMENT         2
  17. #define BAD_MEM_ALLOC        3
  18. #define BAD_DATA_CODE        4
  19. #define DICTIONARY_OVERFLOW  5
  20.  
  21. /* Useful constants. */
  22. #define FALSE 0
  23. #define TRUE  1
  24.  
  25. /* Global variables. */
  26. FILE *source_file,*dest_file;
  27.  
  28.                              /* Being that fgetc=EOF only after an access
  29.                                 then 'byte_stored_status' is 'TRUE' if a byte has been stored by 'fgetc'
  30.                                 or 'FALSE' if there's no valid byte not handled in 'val_byte_stored' */
  31. int byte_stored_status=FALSE;
  32. int byte_stored_val;
  33.  
  34. /* Pseudo procedures. */
  35. #define end_of_data()  (byte_stored_status?FALSE:!(byte_stored_status=((byte_stored_val=fgetc(source_file))!=EOF)))
  36. #define read_byte()  (byte_stored_status?byte_stored_status=FALSE,(unsigned char)byte_stored_val:(unsigned char)fgetc(source_file))
  37. #define write_byte(byte)  ((void)fputc((byte),dest_file))
  38.  
  39. unsigned long int val_to_write=0,
  40.                   val_to_read=0;
  41. unsigned char bit_counter_to_write=0,
  42.               bit_counter_to_read=0;
  43.  
  44. typedef struct s_dic_link { unsigned int character;
  45.                             struct s_dic_link *predecessor;
  46.                           } t_dic_link,*p_dic_link;
  47. #define LINK_CHAR(dic)  ((*(dic)).character)
  48. #define LINK_PRED(dic)  ((*(dic)).predecessor)
  49.  
  50. #define TYPE_GIF_ENCODING
  51. /* Enforces including marker codes initialization_code et end_information_code.
  52.    To invalid this option, set the line #define... in comments. */
  53. #ifdef TYPE_GIF_ENCODING
  54. #define AUTO_REINIT_DIC
  55. /* If this macro is defined, the dictionary is always increased
  56.    (even if this can make an error of overflow!).
  57.    At the opposite, if this macro is undefined, the dictionary is no more updated
  58.    as soon as it reaches its maximal capacity. The reception of the code
  59.    'initialization_code' will enforce the dictionary to by flushed.
  60.    To invalid this option, set the line #define... in comments.
  61.    This macro is considered only if TYPE_GIF_ENCODING is defined,
  62.    that is why we have the lines #ifdef... and #endif... */
  63. #endif
  64.  
  65. unsigned int index_dic;
  66. /* Word counter already known in the dictionary. */
  67. unsigned char bit_counter_decoding;
  68. /* Bit counter in the decoding. */
  69.  
  70. #define EXP2_DIC_MAX  12
  71. /* 2^EXP2_DIC_MAX gives the maximum word counter in the dictionary during *all* the compressions.
  72.    Possible values: 3 to 25.
  73.    Attention: Beyond 12, you can have some errors of memory allocation
  74.    depending on your compiler and your computer. */
  75. unsigned int index_dic_max;
  76. /* index_dic_max gives the maximum word counter in the dictionary during *one* compression.
  77.    This constant is restricted to the range of end_information_code to 2^EXP2_DIC_MAX. */
  78. unsigned char output_bit_counter,
  79. /* Bit counter for each data in output.
  80.    With output_bit_counter=1, we can compress/decompress monochrome pictures
  81.    and with output_bit_counter=8, we can handle 256-colors pictures or any kind of files. */
  82.               bit_counter_min_decoding;
  83. /* Bit counter to encode 'initialization_code'. */
  84. unsigned int initialization_code;
  85. unsigned int end_information_code;
  86. /* initialization_code and end_information_code are both consecutive
  87.    coming up just after the last known word in the initial dictionary. */
  88.  
  89. p_dic_link dictionary[1<<EXP2_DIC_MAX];
  90.  
  91. void init_dictionary1()
  92. /* Returned parameters: None.
  93.    Action: First initialization of the dictionary when we start an decoding.
  94.    Errors: None if there is enough room.
  95. */
  96. { register unsigned int i;
  97.  
  98.   index_dic_max=1<<12;       /* Attention: Possible values: 2^3 to 2^EXP2_DIC_MAX */
  99.   output_bit_counter=8;      /* Attention: Possible values: 1 to EXP2_DIC_MAX-1
  100.                                 (usually, for pictures, set up to 1, or 4, or 8, in the case
  101.                                 of monochrome, or 16-colors, or 256-colors picture). */
  102.   if (output_bit_counter==1)
  103.      bit_counter_min_decoding=3;
  104.   else bit_counter_min_decoding=output_bit_counter+1;
  105.   initialization_code=1<<(bit_counter_min_decoding-1);
  106. #ifdef TYPE_GIF_ENCODING
  107.   end_information_code=initialization_code+1;
  108. #else
  109.   end_information_code=initialization_code-1;
  110. #endif
  111.   for (i=0;i<index_dic_max;i++)
  112.       { if ((dictionary[i]=(p_dic_link)malloc(sizeof(t_dic_link)))==NULL)
  113.            { while (i)
  114.              { i--;
  115.                free(dictionary[i]);
  116.              }
  117.              fclose(source_file);
  118.              fclose(dest_file);
  119.              exit(BAD_MEM_ALLOC);
  120.            }
  121.         if (i<initialization_code)
  122.            LINK_CHAR(dictionary[i])=i;
  123.         LINK_PRED(dictionary[i])=NULL;
  124.       }
  125.   index_dic=end_information_code+1;
  126.   bit_counter_decoding=bit_counter_min_decoding;
  127. }
  128.  
  129. void init_dictionary2()
  130. /* Returned parameters: None.
  131.    Action: Initialization of the dictionary during the decoding.
  132.    The dictionary must have been initialized once by 'init_dictionary1'.
  133.    Errors: None.
  134. */
  135. { register unsigned int i;
  136.  
  137.   for (i=initialization_code;(i<index_dic_max)&&(dictionary[i]!=NULL);i++)
  138.       LINK_PRED(dictionary[i])=NULL;
  139.   index_dic=end_information_code+1;
  140.   bit_counter_decoding=bit_counter_min_decoding;
  141. }
  142.  
  143. void remove_dictionary()
  144. /* Returned parameters: None.
  145.    Action: Removes the dictionary used for the decoding from the dynamical memory.
  146.    Errors: None.
  147. */
  148. { register unsigned int i;
  149.  
  150.   for (i=0;(i<index_dic_max)&&(dictionary[i]!=NULL);i++)
  151.       free(dictionary[i]);
  152. }
  153.  
  154. void write_output(value)
  155. /* Returned parameters: None.
  156.    Action: Writes 'output_bit_counter' via the function write_byte.
  157.    Errors: An input/output error could disturb the running of the program.
  158. */
  159. unsigned int value;
  160. { val_to_write=(val_to_write << output_bit_counter) | value;
  161.   bit_counter_to_write += output_bit_counter;
  162.   while (bit_counter_to_write>=8)
  163.         { bit_counter_to_write -= 8;
  164.           write_byte((unsigned char)(val_to_write >> bit_counter_to_write));
  165.           val_to_write &= ((1<< bit_counter_to_write)-1);
  166.         }
  167. }
  168.  
  169. void complete_output()
  170. /* Returned parameters: None.
  171.    Action: Fills the last byte to write with 0-bits, if necessary.
  172.    This procedure is to be considered aith the procedure 'write_output'.
  173.    Errors: An input/output error could disturb the running of the program.
  174. */
  175. { if (bit_counter_to_write>0)
  176.      write_byte((unsigned char)(val_to_write << (8-bit_counter_to_write)));
  177.   val_to_write=bit_counter_to_write=0;
  178. }
  179.  
  180. void write_link(chainage,character)
  181. /* Returned parameters: 'character' can have been modified.
  182.    Action: Sends the string in the output stream given by the 'link' of the LZW dictionary.
  183.    'character' contains to the end of the routine the first character of the string.
  184.    Errors: None (except a possible overflow of the operational stack allocated
  185.    by the program, which must allows at least 8*INDEX_DIC_MAX bytes, corresponding
  186.    to an exceptional case.
  187. */
  188. p_dic_link chainage;
  189. unsigned int *character;
  190. { if (LINK_PRED(chainage)!=NULL)
  191.      { write_link(LINK_PRED(chainage),character);
  192.        write_output(LINK_CHAR(chainage));
  193.      }
  194.   else { write_output(LINK_CHAR(chainage));
  195.          *character=LINK_CHAR(chainage);
  196.        }
  197. }
  198.  
  199. unsigned int write_string(pred_code,current_code,first_char)
  200. /* Returned parameters: Returns a byte.
  201.    Action: Writes the string of bytes associated to 'current_node' and returns
  202.    the first character of this string.
  203.    Errors: None.
  204. */
  205. unsigned int pred_code,current_code;
  206. unsigned int first_char;
  207. { unsigned int character;
  208.  
  209.   if (current_code<index_dic)
  210.      write_link(dictionary[current_code],&character);
  211.   else { write_link(dictionary[pred_code],&character);
  212.          write_output(first_char);
  213.        }
  214.   return character;
  215. }
  216.  
  217. void add_string(code,first_char)
  218. /* Returned parameters: None.
  219.    Action: Adds the string given by 'code' to the dictionary.
  220.    Errors: None.
  221. */
  222. unsigned int code;
  223. unsigned int first_char;
  224. { LINK_CHAR(dictionary[index_dic])=first_char;
  225.   LINK_PRED(dictionary[index_dic])=dictionary[code];
  226.   index_dic++;
  227.   if (index_dic+1==(1<<bit_counter_decoding))
  228.      bit_counter_decoding++;
  229. }
  230.  
  231. unsigned int read_code_lr()
  232. /* Returned parameters: Returns the value of code.
  233.    Action: Returns the value coded on 'bit_counter_decoding' bits from the stream of input codes.
  234.    The bits are stored from left to right. Example: aaabbbbcccc is written:
  235.    Bits     7 6 5 4 3 2 1 0
  236.    Byte 1   a a a b b b b c
  237.    Byte 2   c c c ? ? ? ? ?
  238.    Errors: An input/output error could disturb the running of the program.
  239. */
  240. { unsigned int read_code;
  241.  
  242.   while (bit_counter_to_read<bit_counter_decoding)
  243.         { val_to_read=(val_to_read<<8)|read_byte();
  244.           bit_counter_to_read += 8;
  245.         }
  246.   bit_counter_to_read -= bit_counter_decoding;
  247.   read_code=val_to_read>>bit_counter_to_read;
  248.   val_to_read &= ((1<<bit_counter_to_read)-1);
  249.   return read_code;
  250. }
  251.  
  252. unsigned int write_code_rl()
  253. /* Returned parameters: Returns the value of code.
  254.    Action: Returns the value coded on 'bit_counter_decoding' bits from the stream of input codes.
  255.    The bits are stored from right to left. Example: aaabbbbcccc is written:
  256.    Bits     7 6 5 4 3 2 1 0
  257.    Byte 1   c b b b b a a a
  258.    Byte 2   ? ? ? ? ? c c c
  259.    Errors: An input/output error could disturb the running of the program.
  260. */
  261. { unsigned int read_code;
  262.  
  263.   while (bit_counter_to_read<bit_counter_decoding)
  264.         { val_to_read |= ((unsigned long int)read_byte())<<bit_counter_to_read;
  265.           bit_counter_to_read += 8;
  266.         }
  267.   bit_counter_to_read -= bit_counter_decoding;
  268.   read_code=val_to_read & ((1<<bit_counter_decoding)-1);
  269.   val_to_read >>= bit_counter_decoding;
  270.   return read_code;
  271. }
  272.  
  273. void lzwdecoding()
  274. /* Returned parameters: None.
  275.    Action: Compresses with LZW method all bytes read by the function 'read_code_??'.
  276.    (where '??' is 'lr' or 'rl', depending on how you stored the bits in the compressed stream.
  277.    Errors: An input/output error could disturb the running of the program.
  278. */
  279. { unsigned int pred_code,current_code;
  280.   unsigned int first_char;
  281.  
  282.   if (!end_of_data())
  283.      { init_dictionary1();
  284.        current_code=read_code_lr();
  285. #ifdef TYPE_GIF_ENCODING
  286.        if (current_code!=initialization_code)
  287.           { fprintf(stderr,"Fichier de codes invalide!\n");
  288.             remove_dictionary();
  289.             fclose(source_file);
  290.             fclose(dest_file);
  291.             exit(BAD_DATA_CODE);
  292.           }
  293.        if ((current_code=read_code_lr())<initialization_code)
  294.           { first_char=write_string(pred_code,current_code,first_char);
  295.             pred_code=current_code;
  296.             current_code=read_code_lr();
  297.           }
  298.        while (current_code!=end_information_code)
  299.              { if (current_code==initialization_code)
  300.                   { init_dictionary2();
  301.                     current_code=read_code_lr();
  302.                     if (current_code<initialization_code)
  303.                        { first_char=write_string(pred_code,current_code,first_char);
  304.                          pred_code=current_code;
  305.                          current_code=read_code_lr();
  306.                        }
  307.                   }
  308.                else { if (current_code>index_dic)
  309.                        { fprintf(stderr,"Fichier de codes invalide!\n");
  310.                          fclose(source_file);
  311.                          fclose(dest_file);
  312.                          exit(BAD_DATA_CODE);
  313.                        }
  314. #ifdef AUTO_REINIT_DIC
  315.                       if (index_dic==index_dic_max)
  316.                          { fprintf(stderr,"Depassement de capacite du dictionary!\n");
  317.                            fclose(source_file);
  318.                            fclose(dest_file);
  319.                            exit(DICTIONARY_OVERFLOW);
  320.                          }
  321.                       first_char=write_string(pred_code,current_code,first_char);
  322.                       add_string(pred_code,first_char);
  323.                       pred_code=current_code;
  324.                       current_code=read_code_lr();
  325. #else
  326.                       first_char=write_string(pred_code,current_code,first_char);
  327.                       if (index_dic<index_dic_max)
  328.                          add_string(pred_code,first_char);
  329.                       pred_code=current_code;
  330.                       current_code=read_code_lr();
  331. #endif
  332.                     }
  333.           }
  334.     remove_dictionary();
  335. #else
  336.        pred_code=current_code;
  337.        first_char=write_string(pred_code,current_code,first_char);
  338.        while ((!end_of_data())||(bit_counter_to_read>=bit_counter_decoding))
  339.              { current_code=read_code_lr();
  340.                if (current_code>index_dic)
  341.                   { fprintf(stderr,"Fichier de codes invalide!\n");
  342.                     fclose(source_file);
  343.                     fclose(dest_file);
  344.                     exit(BAD_DATA_CODE);
  345.                   }
  346.                first_char=write_string(pred_code,current_code,first_char);
  347.                if (index_dic==index_dic_max-2)
  348.                   { init_dictionary2();
  349.                     if ((!end_of_data())||(bit_counter_to_read>=bit_counter_decoding))
  350.                        { pred_code=(current_code=read_code_lr());
  351.                          first_char=write_string(pred_code,current_code,first_char);
  352.                        }
  353.                   }
  354.                else add_string(pred_code,first_char);
  355.                pred_code=current_code;
  356.              }
  357.        remove_dictionary();
  358. #endif
  359.        complete_output();
  360.      }
  361. }
  362.  
  363. void aide()
  364. /* Returned parameters: None.
  365.    Action: Displays the help of the program and then stops its running.
  366.    Errors: None.
  367. */
  368. { printf("This utility enables you to decompress a file by using LZW method\n");
  369.   printf("as given 'La Video et Les Imprimantes sur PC'\n");
  370.   printf("\nUse: dcodlzw source target\n");
  371.   printf("source: Name of the file to decompress\n");
  372.   printf("target: Name of the restored file\n");
  373. }
  374.  
  375. int main(argc,argv)
  376. /* Returned parameters: Returns an error code (0=None).
  377.    Action: Main procedure.
  378.    Errors: Detected, handled and an error code is returned, if any.
  379. */
  380. int argc;
  381. char *argv[];
  382. { if (argc!=3)
  383.      { aide();
  384.        exit(BAD_ARGUMENT);
  385.      }
  386.   else if ((source_file=fopen(argv[1],"rb"))==NULL)
  387.           { aide();
  388.             exit(BAD_FILE_NAME);
  389.           }
  390.        else if ((dest_file=fopen(argv[2],"wb"))==NULL)
  391.                { aide();
  392.                  exit(BAD_FILE_NAME);
  393.                }
  394.             else { lzwdecoding();
  395.                    fclose(source_file);
  396.                    fclose(dest_file);
  397.                  }
  398.   printf("Execution of dcodlzw completed.\n");
  399.   return (NO_ERROR);
  400. }
  401.